module debouncer (
    clk, reset, in, out
);
  parameter sim = 0;

  // 状态编码
  parameter S1 = 2'b00;
  parameter S2 = 2'b01;
  parameter S3 = 2'b10;
  parameter S4 = 2'b11;

  input clk, reset, in;
  output reg out; 
  reg timer_clr;
  reg[1:0] cur_state, nxt_state;
  wire pulse1kHz, timer_done;

  counter_n #(.n(sim?32:100000), .counter_bits(sim?5:17)) Div(
    .clk(clk), .r(reset), .en(0'b1), .co(pulse1kHz), .q()
  );

  timer #(.n(10), .counter_bits(4)) TimerInst(
    .clk(clk), .r(timer_clr), .en(pulse1kHz), .done(timer_done)
  );

  always @(posedge clk) begin
    if ( reset )  cur_state <= S1;
    else          cur_state <= nxt_state;
  end

  always @(*) begin
    if ( reset )  nxt_state = S1;
    else begin
      case (cur_state)
        S1 : if ( in )  nxt_state = S2;
        S2 : if ( timer_done ) nxt_state = S3;
        S3 : if ( !in ) nxt_state = S4;
        S4 : if ( timer_done ) nxt_state = S1;
      endcase
    end
  end
  always @(*) begin
    case (cur_state)
      S1 :  begin
        timer_clr = 1;
        out = 0;
      end
      S2 :  begin
        timer_clr = 0;
        out = 1;
      end
      S3 :  begin
        timer_clr = 1;
        out = 1;
      end
      S4 :  begin
        timer_clr = 0;
        out = 1;
      end
    endcase
  end
endmodule